#include "commonshape.h"
#include "actorbase.h"
#include <osg\ref_ptr>
#include <osg\Geode>
#include <osg\ShapeDrawable>
#include <osg\PositionAttitudeTransform>
#include "datatypedefine.h"
#include <osg\LineWidth>
#include <osg\LineStipple>
#include <osg\PolygonMode>
#include "utility.h"
#include <osg\BlendFunc>

namespace CoreBase
{
	CommonShape::CommonShape()
	{
		_type = -1;
		_defaultStateSet = new osg::StateSet;
		_defaultStateSet->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
		_lineModeStateSet = new osg::StateSet;
		_lineModeStateSet->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
		osg::ref_ptr<osg::PolygonMode> polymode = new osg::PolygonMode;
		polymode->setMode(osg::PolygonMode::FRONT, osg::PolygonMode::LINE);
		_lineModeStateSet->setAttributeAndModes(polymode.get(),osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON);
		osg::ref_ptr<osg::Program> program = new osg::Program;
		program->setName("comshape program");
		_defaultStateSet->setAttributeAndModes( program.get(), osg::StateAttribute::ON );
		_lineModeStateSet->setAttributeAndModes( program.get(), osg::StateAttribute::ON );
		//_defaultStateSet->setMode(osg::StateAttribute::PROGRAM, osg::StateAttribute::OFF/*| osg::StateAttribute::PROTECTED*/);
		//_lineModeStateSet->setMode(osg::StateAttribute::PROGRAM, osg::StateAttribute::OFF/*| osg::StateAttribute::PROTECTED*/);
		//_defaultStateSet->setMode(GL_BLEND,osg::StateAttribute::ON);
		//_defaultStateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); 
		//_defaultStateSet->setRenderBinDetails(1000, "DepthSortedBin"); 
	}
	CommonShapeBox::CommonShapeBox(int type,CoreBase::ActorBase* owneractor,const QString& name):CoreBase::Transformable(owneractor,name)
		,_x(0),_y(0),_z(1),_scalZ(1.0f),_startShow(false)
	{
		_type = type;
	}

	CommonShapeBox::CommonShapeBox(int type,osg::MatrixTransform& node,CoreBase::ActorBase* owneractor, const QString& name)
		:CoreBase::Transformable(node,owneractor,name),_x(0),_y(0),_z(0),_startShow(false)
	{
		_type = type;
	}

	CommonShapeBox::~CommonShapeBox()
	{}

	void CommonShapeBox::createBox(osg::BoundingBox& box,float heightpercent,const osg::Vec4& color,bool opacity)
	{
		createBox(box.center(),box.zMin(),box.xMax()-box.xMin(),box.yMax()-box.yMin(),
				(box.zMax()-box.zMin())*heightpercent,color,opacity);
	}

	void CommonShapeBox::createBox(const osg::Vec3& center,float bottomz,float x,float y,float z,const osg::Vec4& color,bool opacity)
	{
		_center = center;
		_x = x;
		_y = y;
		_scalZ = z;
		_color = color;
		_bottomZ = bottomz;
		_opacity = opacity;
		_pBox = new osg::Box(osg::Vec3(0,0,0),_x,_y,_z);
		_pLineBox = new osg::Box(osg::Vec3(0,0,0),_x,_y,_z);
		_boxShape = new osg::ShapeDrawable(_pBox.get());
		_lineBoxShape = new osg::ShapeDrawable(_pLineBox.get());
		osg::ref_ptr<osg::Geode> boxgeode = new osg::Geode();
		osg::ref_ptr<osg::Geode> linegeode = new osg::Geode();
		boxgeode->addDrawable(_boxShape.get());
		linegeode->addDrawable(_lineBoxShape.get());
		if(!_boxTransform.valid())
		{
			_boxTransform = new osg::PositionAttitudeTransform;
			boxgeode->setStateSet(_defaultStateSet);
			linegeode->setStateSet(_lineModeStateSet);
		}
		_boxTransform->addChild(boxgeode);
		_boxTransform->addChild(linegeode);
		_boxTransform->setPosition(osg::Vec3(_center.x(),_center.y(),_bottomZ));
		_boxTransform->addUpdateCallback(new ShapeSizeUpdateCallback(this));
		_boxShape->setColor(color);
		_lineBoxShape->setColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
	}

	void CommonShapeBox::startShow()
	{
		_startShow = true;
		float nowz = _boxTransform->getPosition().z();
		_boxTransform->setPosition(osg::Vec3(_center.x(),_center.y(),_bottomZ));//_center.z()-_scalZ/2.0f));
		_boxTransform->setScale(osg::Vec3(1.0f,1.0f,1.0f));
		_z = 1.0f;
	}

	void CommonShapeBox::updateSize()
	{
		if(_startShow)
		{
			_z++;
			_boxTransform->setScale(osg::Vec3(1.0f,1.0f,_z));
			_boxTransform->setPosition(osg::Vec3(_center.x(),_center.y(),_bottomZ+_z/2.0f));//(_center.z()-_scalZ/2.0f)+_z/2.0f));
			if(_z>=_scalZ)
				_startShow = false;
		}
	}

	osg::Node* CommonShapeBox::getOSGNode()
	{
		return _boxTransform;
	}

	const osg::Node* CommonShapeBox::getOSGNode() const
	{
		return _boxTransform;
	}

	void CommonShapeBox::setColor(const osg::Vec4& color)
	{
		_color = color;
		_boxShape->setColor(color);
	}

	void CommonShapeBox::setSize(float x,float y,float z)
	{
		_x = x;
		_y = y;
		_scalZ = z;
	}

	void CommonShapeBox::setRadious(float radious)
	{
		if((radious!=_x || radious!=_y) && radious>0)
			setSize(radious,radious,_scalZ);
	}

	void CommonShapeBox::setHeight(float height)
	{
		if(height!=_scalZ && height>0)
		{
			setSize(_x,_y,height);
		}
	}

	LineRectShape::LineRectShape(bool hud):Drawable(NULL,"LineRectShape"),_isupdateSize(false),_hudCamera(NULL)
	{
		_isHud = hud;
		if(hud)
		{
			createHudCamera();
			_hudCamera->addChild(createRealNode(osg::Vec3(0,0,0),1.0f,1.f,0,osg::Vec4(0,0.8f,0,1)));
		}
		else
		{
			_transformNode = new osg::MatrixTransform ;
			_transformNode->addChild(createRealNode(osg::Vec3(0,0,0),1.0f,1.f,0,osg::Vec4(0,1.0f,0,1)));
		}
	}

	osg::Group* LineRectShape::createRealNode(const osg::Vec3& center,float width,float length,int plane,const osg::Vec4& color,bool corner) 
	{
		_realnode = new osg::Geode ; 
		_realnode->setUpdateCallback( new LineRectUpdateCallback(this) ) ;
		osg::StateSet *ss = _realnode->getOrCreateStateSet() ;
		ss->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF|osg::StateAttribute::PROTECTED);
		ss->setMode(GL_LIGHTING,osg::StateAttribute::OFF|osg::StateAttribute::PROTECTED);
		//ss->setRenderBinDetails( RENDERBIN_ORDER_LINERECT, "RenderBin") ;
		_realgeo = new osg::Geometry ;
		_realnode->addDrawable( _realgeo ) ;
		cvertex = new osg::Vec3Array ;
		indexset = new osg::DrawElementsUInt(osg::PrimitiveSet::LINE_LOOP, 0);
		_colorsData = new osg::Vec4Array ; 	
		_colorsData->push_back(color) ;
		_colorsIndexData = new osg::TemplateIndexArray<unsigned int, osg::Array::UIntArrayType,4,4>;
		osg::Vec3 vp0, vp1 ;
		if( plane == 0 )
		{
			vp0 = osg::Vec3( width, 0.0f, 0.0f ) ;
			vp1 = osg::Vec3( 0.0f, width,0.0f ) ;
		}
		if(corner)
			_vbase  = center;
		else
			_vbase = center - (vp1+vp0)/2.0f;
		_plane = plane ;
		_vsets.clear() ;
		_vsets.push_back( _vbase ) ;
		_vsets.push_back( _vbase + vp0 ) ;
		_vsets.push_back( _vbase + vp0 + vp1 ) ;
		_vsets.push_back( _vbase + vp1 ) ;
		for( unsigned i=0; i<_vsets.size(); i++ )
		{
			cvertex->push_back( _vsets[i] ) ;
			indexset->push_back( i ) ;
		}
		_colorsIndexData->push_back( 0 ) ;
		_realgeo->setVertexArray( cvertex ) ;
		_realgeo->addPrimitiveSet(indexset);
		_realgeo->setColorArray(_colorsData) ;
		_realgeo->setColorIndices(_colorsIndexData) ;
		_realgeo->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE);
		return (osg::Group*)(_realnode.get()) ;
	}

	void LineRectShape::viewResize(const int w,const int h)
	{
		_hudCamera->setProjectionMatrix(osg::Matrix::ortho2D(0,w,0,h));
	}

	void LineRectShape::updateSize(const osg::Vec3& center,int w,int l,bool corner)
	{
		_vbase  = center;
		osg::Vec3 vp0, vp1 ;
		if( _plane == 0 )
		{
			vp0 = osg::Vec3( w, 0.0f,0.0f ) ;
			vp1 = osg::Vec3( 0.0f,l,0.0f) ;
		}
		if(corner)
			_vbase  = center;
		else
			_vbase = center - (vp1+vp0)/2.0f;
		_vsets.clear() ;
		_vsets.push_back( _vbase ) ;
		_vsets.push_back( _vbase + vp0 ) ;
		_vsets.push_back( _vbase + vp0 + vp1 ) ;
		_vsets.push_back( _vbase + vp1 ) ;
		_isupdateSize = true ;
		update();
	}

	void LineRectShape::update()
	{
		if( _isupdateSize )
		{
			cvertex->clear() ;
			indexset->clear() ;
			int numbers = _realgeo->getNumPrimitiveSets() ;
			_realgeo->removePrimitiveSet(0, numbers);
			for( unsigned i=0; i<_vsets.size(); i++ )
			{
				cvertex->push_back( _vsets[i] ) ;
				indexset->push_back( i );
			}
			_realgeo->setVertexArray( cvertex ) ;
			_realgeo->addPrimitiveSet(indexset);
		}
		_isupdateSize = false;
	}

	void LineRectShape::createHudCamera()
	{
		_hudCamera = new osg::Camera;
		_hudCamera->setProjectionMatrix(osg::Matrix::ortho2D(0,1024,0,768));
		_hudCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
		_hudCamera->setViewMatrix(osg::Matrix::identity());
		_hudCamera->setClearMask(GL_DEPTH_BUFFER_BIT);
		_hudCamera->setRenderOrder(osg::Camera::POST_RENDER);
		_hudCamera->setAllowEventFocus(false);
	}

	osg::Node* LineRectShape::getOSGNode()
	{
		if(_isHud)
			return _hudCamera.get();
		else
			_transformNode.get();
	}

	const osg::Node* LineRectShape::getOSGNode() const
	{
		if(_isHud)
			return _hudCamera.get();
		else
			_transformNode.get();
	}

	CircleShape::CircleShape(const osg::Vec3& center,float radius,int slice,float width,const osg::Vec4& color, osg::StateSet* ss)
		:Drawable(NULL,"CircleShape")
	{
		_center = center ;
		_radius=radius;
		_slice = slice ;
		_color = color ;
		_width=width;
		_transformNode = new osg::MatrixTransform ;
		_gNode = new osg::Geode ;
		_geode     = new osg::Geometry ;
		_vArray = new osg::Vec3Array ;
		_cArray = new osg::Vec4Array ;
		_cArray->push_back( _color ) ;
		//_gNode->setUpdateCallback( new circleShapeUpdateCallback(this) ) ;
		if( ss )
			_gNode->setStateSet( ss ) ;
		else
		{
			osg::StateSet* ss = _gNode->getOrCreateStateSet() ;
			osg::LineWidth *lw=new osg::LineWidth;
			lw->setWidth(_width);
			osg::LineStipple* ls=new osg::LineStipple();
			ss->setAttributeAndModes(lw,osg::StateAttribute::ON|osg::StateAttribute::PROTECTED);
			ss->setAttributeAndModes(ls,osg::StateAttribute::ON|osg::StateAttribute::PROTECTED);
			ss->setMode(GL_LIGHTING,osg::StateAttribute::OFF|osg::StateAttribute::PROTECTED);
		}
		_geode->setVertexArray( _vArray ) ;
		_geode->setColorArray( _cArray ) ;
		_geode->setColorBinding( osg::Geometry::BIND_PER_PRIMITIVE );
		_gNode->addDrawable( _geode ) ;
		_transformNode->addChild( _gNode ) ;
		//do firstly
		//SET_RESPFLAG_ACTIVE( redraw ) ;
	}

	osg::Node* CircleShape::getOSGNode()
	{
		return _transformNode.get();
	}

	const osg::Node* CircleShape::getOSGNode() const
	{
		return _transformNode.get();
	}

	void CircleShape::update() 
	{
		clear() ;
		for(int i=0;i<_slice;i++)
		{
			osg::Vec3 point;
			float a=i*2*M_PI/_slice+M_PI/4;
			point.x()=_center.x()+_radius*cos(a);;
			point.y()=_center.y()+_radius*sin(a);
			point.z()=10.0;
			_vArray->push_back(point);
		}
		_geode->setVertexArray( _vArray ) ;
		_geode->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINE_LOOP, 0, _vArray->size()));
	}

	void CircleShape::reDraw(const osg::Vec3 &center,float radius,int slice)
	{
		_center=center;
		_radius=radius;
		_slice=slice;
		update();
	}

	void CircleShape::setCenter(const osg::Vec3 &point) 
	{
		_center=point;
		update();
	}

	osg::Vec3 CircleShape::getCenter()
	{
		return _center;
	}

	void CircleShape::setRadius(float &radius) 
	{
		_radius=radius;
		update();
	}

	float CircleShape::getRadius()
	{
		return _radius;
	}

	void CircleShape::setSlice(int &number)
	{
		_slice=number;
		update();
	}

	int CircleShape::getSlice()
	{
		return _slice;
	}

	void CircleShape::setColor(const osg::Vec4& color ) 
	{
		_color=color;
		_cArray->clear();
		_cArray->push_back(_color);
		_geode->setColorArray( _cArray ) ;
	}

	osg::Vec4  CircleShape::getColor()
	{
		return _color;
	}

	void CircleShape::setWidth(float &width)
	{
		_width=width;
		osg::StateSet* ss = _gNode->getOrCreateStateSet() ;
		osg::LineWidth* lw=new osg::LineWidth;
		lw->setWidth(_width);
		ss->setAttributeAndModes(lw,osg::StateAttribute::ON|osg::StateAttribute::PROTECTED);
	}

	float CircleShape::getWidth()
	{
		return _width;
	}

	void CircleShape::clear()
	{
		_vArray->clear() ;
		int primnums = _geode->getNumPrimitiveSets() ;
		_geode->removePrimitiveSet( 0, primnums ) ;
	}

	PlaneShape::PlaneShape():Drawable(NULL,"PlaneShape"),_ss(NULL),_color(0,1,0,1)
	{
		initDrawable();
	}

	void PlaneShape::initDrawable()
	{
		_transformNode = new osg::MatrixTransform ;
		_gNode = new osg::Geode;
		_geode = new osg::Geometry;
		_vArray = new osg::Vec3Array;
		_cArray = new osg::Vec4Array;
		_tArray = new osg::Vec2Array;
		_cArray->push_back(_color);
		if(_ss)
			_gNode->setStateSet(_ss);
		_geode->setVertexArray(_vArray );
		_geode->setColorArray(_cArray );
		_geode->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE );
		_gNode->addDrawable(_geode);
		_transformNode->addChild(_gNode);
		//line
		_lineGeode = new osg::Geode;
		_lineGeometry = new osg::Geometry;
		_lineVArray  = new osg::Vec3Array;
		_lineCArray = new osg::Vec4Array;
		_lineCArray->push_back(_color);
		_lineGeometry->setVertexArray(_lineVArray );
		_lineGeometry->setColorArray(_lineCArray );
		_lineGeometry->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE );
		_lineGeode->addDrawable(_lineGeometry);
	}

	void PlaneShape::setColor(const osg::Vec4& color)
	{
		if(color!=_color)
		{
			_color = color;
			_cArray->clear();
			_lineCArray->clear();
			_cArray->push_back(_color);
			_lineCArray->push_back(_color);
			_geode->setColorArray(_cArray );
			_lineGeometry->setColorArray(_lineCArray );
		}
	}

	void PlaneShape::reset(const osg::Vec3& p1,const osg::Vec3& p2,const osg::Vec3& p3,
			const osg::Vec2& t1,const osg::Vec2& t2,const osg::Vec2& t3,osg::StateSet* ss)
	{
		_p1 = p1;
		_p2 = p2;
		_p3 = p3;
		_ss = ss;
		clear();
		_vArray->push_back(p1);
		_vArray->push_back(p2);
		_vArray->push_back(p3);
		_tArray->push_back(t1);
		_tArray->push_back(t2);
		_tArray->push_back(t3);
		_geode->setVertexArray(_vArray);
		_geode->setColorArray(_cArray);
		_geode->setTexCoordArray(0,_tArray);
		_geode->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE_SET);
		_geode->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::TRIANGLES, 0, _vArray->size())) ;
		if(ss)
		{
			_gNode->setStateSet(ss);
			_ss = ss;
		}
	}

	void PlaneShape::reset(const osg::Vec3& p1,const osg::Vec3& p2,const osg::Vec3& p3,const osg::Vec3& p4,
			const osg::Vec2& t1,const osg::Vec2& t2,const osg::Vec2& t3,const osg::Vec2& t4,osg::StateSet* ss)
	{
		_p1 = p1;
		_p2 = p2;
		_p3 = p3;
		_p4 = p4;
		_ss = ss;
		clear();
		_vArray->push_back(p1);
		_vArray->push_back(p2);
		_vArray->push_back(p3);
		_vArray->push_back(p4);
		_tArray->push_back(t1);
		_tArray->push_back(t2);
		_tArray->push_back(t3);
		_tArray->push_back(t4);
		osg::ref_ptr<osg::Vec3Array> nor = new osg::Vec3Array;
		osg::Vec3f normalvec3 = p1^p2;
		nor->push_back(normalvec3);
		_geode->setVertexArray(_vArray);
		_geode->setColorArray(_cArray);
		_geode->setTexCoordArray(0,_tArray);
		_geode->setNormalArray(nor);
		_geode->setNormalBinding( osg::Geometry::BIND_PER_PRIMITIVE_SET );
		_geode->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE_SET);
		_geode->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::QUADS,0,_vArray->size()));
		if(ss)
		{
			_gNode->setStateSet(ss);
			_ss = ss;
		}
	}

	osg::Node* PlaneShape::getOSGNode()
	{
		return _transformNode.get();
	}

	const osg::Node* PlaneShape::getOSGNode() const
	{
		return _transformNode.get();
	}

	void PlaneShape::clear()
	{
		_vArray->clear();
		_tArray->clear();
		int primnums = _geode->getNumPrimitiveSets();
		_geode->removePrimitiveSet(0,primnums);
	}

	void PlaneShape::showPlaneLine(bool show)
	{
		if(_showPlaneLine!=show)
		{
			_showPlaneLine = show;
			if(_showPlaneLine)
				updateLine(_linePointVector);
			else
				_transformNode->removeChild(_lineGeode);
		}
	}

	void PlaneShape::updateLine(std::vector<osg::Vec3> pointvector)
	{
		_linePointVector = pointvector;
		//clear
		_lineVArray->clear() ;
		int primnums = _lineGeometry->getNumPrimitiveSets() ;
		_lineGeometry->removePrimitiveSet( 0, primnums ) ;
		for(int i=0;i<pointvector.size();++i)
		{
			_lineVArray->push_back(pointvector.at(i));
		}
		_lineGeometry->setVertexArray( _lineVArray ) ;
		_lineGeometry->setColorArray( _lineCArray ) ;
		_lineGeometry->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE_SET);
		_lineGeometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINE_LOOP,0,_lineVArray->size()));
		_transformNode->addChild(_lineGeode);
	}

	UserDefineShape::UserDefineShape(CoreBase::ActorBase* owneractor,float height,const osg::Vec4& color):Transformable(owneractor,"UserDefineShape")
	{
		_height = height;
		_color = color;
		initDrawable();
	}

	void UserDefineShape::setHeight(float height)
	{
		if(_height != height)
		{
			_height = height;
			if(_vertexVector.size()>1)
			{
				setUserDefineVertex(_vertexVector,false);
			}
		}
	}

	float UserDefineShape::getHeight()
	{
		return _height;
	}

	void UserDefineShape::setColor(const osg::Vec4& color)
	{
		if(_color != color)
		{
			_color=color;
			_cArray->clear();
			_lineCArray->clear();
			_cArray->push_back(_color);
			unsigned int num = _topIndexSet->getNumPrimitives();
			for(unsigned int i = 0;i<num;++i)
				_cArray->push_back(_color);
			_geomerty->setColorArray(_cArray);
			unsigned int linenum  = _lineIndexSet->getNumPrimitives();
			for(unsigned int i = 0;i<linenum;++i)
				_lineCArray->push_back(_color);
			_lineGeometry->setColorArray(_lineCArray);
		}
	}

	osg::Vec4 UserDefineShape::getColor()
	{
		return _color;
	}

	void UserDefineShape::clear()
	{
		_vArray->clear();
		int primnums = _geomerty->getNumPrimitiveSets();
		_geomerty->removePrimitiveSet(0,primnums);
		_lineVArray->clear();
		primnums = _lineGeometry->getNumPrimitiveSets();
		_lineGeometry->removePrimitiveSet(0,primnums);
		_lineIndexSet->clear() ;
		_indexSet->clear();
		_topIndexSet->clear();
		_cArray->clear();
		_lineCArray->clear();
	}

	osg::Node* UserDefineShape::getOSGNode()
	{
		return _transformNode;
	}

	const osg::Node* UserDefineShape::getOSGNode() const
	{
		return _transformNode;
	}

	void UserDefineShape::setUserDefineVertex(std::vector<osg::Vec3> vertexvector,bool end)
	{
		_vertexVector = vertexvector;
		_topVertexVector.clear();
		for(int i=0;i<_vertexVector.size();++i)
		{
			VertexStruct pointstruct;
			pointstruct._point = osg::Vec3(_vertexVector.at(i).x(),_vertexVector.at(i).y(),_height);
			_topVertexVector.push_back(pointstruct);
		}
		clear();
		for(int i=0;i<_vertexVector.size();++i)
		{
			osg::Vec3 p0 = _vertexVector.at(i);
			osg::Vec3 p1 = _topVertexVector.at(i)._point;
			_vArray->push_back(p0);
			_vArray->push_back(p1);
			_topVertexVector[i]._index = _vArray->size()-1;
			_indexSet->push_back(2*i);
			_indexSet->push_back(2*i+1);

			_lineVArray->push_back(p0);
			_lineVArray->push_back(p1);
			_lineIndexSet->push_back(2*i);
			_lineIndexSet->push_back(2*i+1);
			if(i!=0)
			{
				_lineIndexSet->push_back(2*i-1);
				_lineIndexSet->push_back(2*i+1);
			}
		}
		if(end)
		{
			_lineIndexSet->push_back(1);
			_lineIndexSet->push_back(_indexSet->size()-1);
			_indexSet->push_back(0);
			_indexSet->push_back(1);
			bool ccw = shapeIsCounterclockwise(_vertexVector);
			refreshTopPlane(_topVertexVector,ccw);
		}
		_lineGeometry->setVertexArray(_lineVArray);
		_lineGeometry->addPrimitiveSet(_lineIndexSet);
		_geomerty->setVertexArray(_vArray);
		_geomerty->addPrimitiveSet(_indexSet);
		_geomerty->addPrimitiveSet(_topIndexSet);
		_cArray->push_back(_color);
		if(end)
		{
			unsigned int num = _topIndexSet->getNumPrimitives();
			for(unsigned int i = 0;i<num;++i)
				_cArray->push_back(_color);
		}
		_geomerty->setColorArray(_cArray);
		unsigned int linenum  = _lineIndexSet->getNumPrimitives();
		for(unsigned int i = 0;i<linenum;++i)
			_lineCArray->push_back(_color);
		_lineGeometry->setColorArray(_lineCArray);
	}

	void UserDefineShape::refreshTopPlane(std::vector<VertexStruct> vertexvector,bool iscounterclockwise)
	{
		std::vector<VertexStruct> newvector;
		if(vertexvector.size()>2)
		{
			osg::Vec3 p0;
			osg::Vec3 p1;
			osg::Vec3 p2;
			for(int i=0;i<vertexvector.size();++i)
			{
				if(i == vertexvector.size() -1)
				{
					newvector.push_back(vertexvector.at(i));
					newvector.push_back(vertexvector.at(0));
					refreshTopPlane(newvector,iscounterclockwise);
					break;
				}
				if(i+1 == vertexvector.size() -1)
				{
					p0 = vertexvector.at(i)._point;
					p1 = vertexvector.at(i+1)._point;
					p2 = vertexvector.at(0)._point;
					osg::Vec3 nor = (p1 - p0)^(p2 - p1);
					bool isvalidtriangle = true;
					for(int j=0;j<vertexvector.size();++j)
					{
						isvalidtriangle = pointInTriangle(osg::Vec2(p0.x(),p0.y()),osg::Vec2(p1.x(),p1.y()),
							osg::Vec2(p2.x(),p2.y()),osg::Vec2(vertexvector.at(j)._point.x(),vertexvector.at(j)._point.y()));
						if(!isvalidtriangle)
							break;
					}
					if(nor.z()>0 && iscounterclockwise || !iscounterclockwise && nor.z()<0 
						&& isvalidtriangle)
					{
						_topIndexSet->push_back(vertexvector.at(i)._index);
						_topIndexSet->push_back(vertexvector.at(i+1)._index);
						_topIndexSet->push_back(vertexvector.at(0)._index);
						if(i!=0)
							newvector.push_back(vertexvector.at(i));
					}
					else
					{
						if(i!=0)
							newvector.push_back(vertexvector.at(i));
						newvector.push_back(vertexvector.at(i+1));
					}
					newvector.push_back(vertexvector.at(0));
					refreshTopPlane(newvector,iscounterclockwise);
					break;
				}
				p0 = vertexvector.at(i)._point;
				p1 = vertexvector.at(i+1)._point;
				p2 = vertexvector.at(i+2)._point;
				osg::Vec3 nor = (p1 - p0)^(p2 - p1);
				bool isvalidtriangle = true;
				for(int j=0;j<vertexvector.size();++j)
				{
					isvalidtriangle = pointInTriangle(osg::Vec2(p0.x(),p0.y()),osg::Vec2(p1.x(),p1.y()),
						osg::Vec2(p2.x(),p2.y()),osg::Vec2(vertexvector.at(j)._point.x(),vertexvector.at(j)._point.y()));
					if(!isvalidtriangle)
						break;
				}
				if(nor.z()>0 && iscounterclockwise || !iscounterclockwise && nor.z()<0 && isvalidtriangle)
				{
					_topIndexSet->push_back(vertexvector.at(i)._index);
					_topIndexSet->push_back(vertexvector.at(i+1)._index);
					_topIndexSet->push_back(vertexvector.at(i+2)._index);
					if(i!=0)
						newvector.push_back(vertexvector.at(i));
				}
				else if(vertexvector.size()!=3)
				{
					if(i!=0)
						newvector.push_back(vertexvector.at(i));
					newvector.push_back(vertexvector.at(i+1));
				}
				i++;
			}
		}
	}

	void UserDefineShape::getUserDefineVertex(std::vector<osg::Vec3>& vertexvector)
	{
		vertexvector = _vertexVector;
	}

	void UserDefineShape::initDrawable()
	{
		_transformNode = new osg::MatrixTransform ;
		_geode = new osg::Geode;
		_geomerty = new osg::Geometry;
		_vArray = new osg::Vec3Array;
		_cArray = new osg::Vec4Array;
		//_tArray = new osg::Vec2Array;
		_geomerty->setVertexArray(_vArray);
		_geomerty->setColorArray(_cArray);
		_indexSet = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLE_STRIP);
		_topIndexSet = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES);
		_geomerty->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE);
		_geode->addDrawable(_geomerty);
		//line
		_lineGeode = new osg::Geode;
		_lineGeometry = new osg::Geometry;
		_lineVArray  = new osg::Vec3Array;
		_lineCArray = new osg::Vec4Array;
		_lineGeometry->setVertexArray(_lineVArray);
		_lineGeometry->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE);
		_lineGeode->addDrawable(_lineGeometry);
		_lineIndexSet = new osg::DrawElementsUInt(osg::PrimitiveSet::LINES,0);

		osg::StateSet* ss = _geomerty->getOrCreateStateSet() ;
		ss->setMode(GL_LIGHTING, osg::StateAttribute::OFF|osg::StateAttribute::PROTECTED) ;
		osg::ref_ptr<osg::Program> program = new osg::Program;
		program->setName("area program");
		ss->setAttributeAndModes( program.get(), osg::StateAttribute::ON );
		osg::BlendFunc* bf = new
			osg::BlendFunc(osg::BlendFunc::SRC_ALPHA,osg::BlendFunc::ONE_MINUS_SRC_ALPHA );
		ss->setAttributeAndModes(bf);
		ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
		ss->setRenderBinDetails(20, "DepthSortedBin");
		_transformNode->addChild(_geode);
		_transformNode->addChild(_lineGeode);
	}

	CommonCylinder::CommonCylinder(CoreBase::ActorBase* owneractor,const QString& name):
	CoreBase::Transformable(owneractor,name)
	{
		_node = new osg::Group;
	}

	CommonCylinder::~CommonCylinder()
	{}

	void CommonCylinder::setCylinderSetting(float radius,int facenum,const osg::Vec3& startp,float height,const osg::Vec4& color,
		bool withtop,bool withbottom,bool withcenter)
	{
		_withTop = withtop;
		_withBottom = withbottom;
		_withCenter = withcenter;
		osg::Vec3 u,v;
		osg::Vec3 endp = startp + osg::Vec3(0,0,height);
		osg::Vec3 normal = startp - endp;
		getVUValue(normal,u,v);
		QVector<osg::Vec3> startpointvec = computePointVec(startp,radius,facenum,u,v);
		QVector<osg::Vec3> endpointvec = computePointVec(endp,radius,facenum,u,v);
		osg::ref_ptr<osg::Vec3Array> tvarray = new osg::Vec3Array;
		osg::ref_ptr<osg::Vec3Array> cvarray = new osg::Vec3Array;
		osg::ref_ptr<osg::Vec3Array> bvarray = new osg::Vec3Array;
		bvarray->push_back(startp);
		for(int j=0;j<startpointvec.size();++j)
		{
			cvarray->push_back(startpointvec.at(j));
			bvarray->push_back(startpointvec.at(j));
		}
		cvarray->push_back(startpointvec.at(0));
		bvarray->push_back(startpointvec.at(0));
		tvarray->push_back(endp);
		for(int j=0;j<endpointvec.size();++j)
		{
			tvarray->push_back(endpointvec.at(j));
			cvarray->push_back(endpointvec.at(j));
		}
		tvarray->push_back(endpointvec.at(0));
		cvarray->push_back(endpointvec.at(0));
		int ind1, ind2, ind3, ind4;
		if(withcenter)
		{
			osg::ref_ptr<osg::DrawElementsUInt> indexset = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS,0);
			for(int m = 0;m<facenum;m++)
			{
				ind1 = m + 0*(facenum+1)*2;
				ind2 = 1+ ind1+facenum;
				ind3 = ind2 + 1;
				ind4 = ind1+1;
				indexset->push_back( ind1 ) ;
				indexset->push_back( ind2 ) ;
				indexset->push_back( ind3 ) ;
				indexset->push_back( ind4 ) ;
			}
			osg::ref_ptr<osg::Geometry> cgeometry = new osg::Geometry;
			cgeometry->setVertexArray(cvarray);
			cgeometry->addPrimitiveSet(indexset.get());
			_centerGeode = new osg::Geode;
			_centerGeode->addDrawable(cgeometry);
			_node->addChild(_centerGeode);
		}
		if(withbottom)
		{
			osg::ref_ptr<osg::DrawElementsUInt> triangleset1 = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES,0);
			for(int m = 0;m<facenum;m++)
			{
				ind1 = 0;
				ind2 = m+1;
				ind3 = ind2+1;
				triangleset1->push_back(ind1);
				triangleset1->push_back( ind2);
				triangleset1->push_back( ind3);
			}
			osg::ref_ptr<osg::Geometry> bgeometry = new osg::Geometry;
			bgeometry->setVertexArray(bvarray);
			bgeometry->addPrimitiveSet(triangleset1.get());
			_bottomGeode = new osg::Geode;
			_bottomGeode->addDrawable(bgeometry);
			_node->addChild(_bottomGeode);
		}
		if(withtop)
		{
			osg::ref_ptr<osg::DrawElementsUInt> triangleset2 = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES,0);
			for(int m = 0;m<facenum;m++)
			{
				ind1 = 0;
				ind2 = m+1;
				ind3 = ind2+1;
				triangleset2->push_back(ind1);
				triangleset2->push_back( ind2);
				triangleset2->push_back( ind3);
			}
			osg::ref_ptr<osg::Geometry> tgeometry = new osg::Geometry;
			tgeometry->setVertexArray(tvarray);
			tgeometry->addPrimitiveSet(triangleset2.get());
			_topGeode = new osg::Geode;
			_topGeode->addDrawable(tgeometry);
			_node->addChild(_topGeode);
		}
	}

	osg::ref_ptr<osg::StateSet> CommonCylinder::getOrCreateTopStateSet()
	{
		if(_topGeode.valid())
			return _topGeode->getOrCreateStateSet();
		return NULL;
	}

	osg::ref_ptr<osg::StateSet> CommonCylinder::getOrCreateCenterStateSet()
	{
		if(_centerGeode.valid())
			return _centerGeode->getOrCreateStateSet();
		return NULL;
	}

	osg::ref_ptr<osg::StateSet> CommonCylinder::getOrCreateBottomStateSet()
	{
		if(_bottomGeode.valid())
			return _bottomGeode->getOrCreateStateSet();
		return NULL;
	}

	osg::Node* CommonCylinder::getOSGNode()
	{
		return _node;
	}

	const osg::Node* CommonCylinder::getOSGNode() const
	{
		return _node;
	}

	QVector<osg::Vec3> CommonCylinder::computePointVec(const osg::Vec3& centerpoint,float radius,int facenum
		,const osg::Vec3& mu,const osg::Vec3& mv)
	{
		QVector<osg::Vec3> mvec;
		for(int i=0;i<facenum;i++)
		{
			float angle = i*osg::PI*2/facenum;
			osg::Vec3 point = centerpoint+mu*(radius*cos(angle)) + mv*(radius*sin(angle));
			mvec.push_back(point);
		}
		return mvec;
	}
}